/*
 * Character.cpp
 *
 *  Created on: Oct 8, 2011
 *  Created by: Devin Manno
 *  Updated by: Devin Manno,
 *	Last Update: Oct 14, 2011
 */
#include "Character.h"
#include <stdexcept>

Character::Character(string playerName, CharClass cClass, std::string objectType) : Base(objectType) {  //initialize fixed size and NULL values
	setDesc(playerName);

	dead = false;				// character was just created, it's not dead yet!
	characterClass = cClass;
	AttackType attack0("Melee", 50, 0);	// add basic attack for all Characters (swing weapon)
	unlockedAttacks.push_back(true);	// sets attack 0 to true meaning it is unlocked
	attacks.push_back(attack0);		// add basic attack to attacks vector
	EquipmentType *H = new EquipmentType(HEAD);
	equipment.push_back(H);
	EquipmentType *C = new EquipmentType(CHEST);
	equipment.push_back(C);
	EquipmentType *P = new EquipmentType(PANTS);
	equipment.push_back(P);
	EquipmentType *G = new EquipmentType(GLOVES);
	equipment.push_back(G);
	EquipmentType *F = new EquipmentType(FEET);
	equipment.push_back(F);
	EquipmentType *W = new EquipmentType(WEAPON);
	equipment.push_back(W);
}

Character::~Character() {
	// TODO Auto-generated destructor stub
}

// getters
/*
 * getNumAttacks
 * Description: gets the number of attacks the character can choose from
 * Pre: none
 * Post: none
 * Returns: the number of attack abilities the character has
 */
int Character::getNumAttacks() const{

	unsigned int count = 0;
	for(unsigned int i = 0; i< unlockedAttacks.size(); i++){
		if(unlockedAttacks[i])
			count++;
	}
	return count;
}


bool Character::getAttackType(int attackIndex, AttackType& attack)
{
	try {
		attack = attacks.at(attackIndex);
	}
	catch( out_of_range& e ) {
		return false;
	}

	return true;
}

/*
 * isDead
 * Description: checks to see if the player is dead
 * Pre: none
 * Post: none
 * Returns: true if the player is dead, false otherwise
 */
bool Character::isDead() const{
	return dead;
}

/*
 * getEquipment
 * Description: access to the character's equipment slots for GUI and controller classes.
 * Pre: none
 * Post: none
 * Returns: a const ref (read-only) to character's equipment
 */

const vector<EquipmentType*>& Character::getEquipment() const{
	return equipment;
}

CharClass Character::getCharClass() const{
	return characterClass;
}

const vector<AttackType>* Character::getAttacks(){
	vector<AttackType>* atk = new vector<AttackType>();
	for(int i = 0; i < unlockedAttacks.size();i++){
		if(unlockedAttacks[i])
			atk->push_back(attacks[i]);
	}
	return atk;
}

// setters


/*
 * setDead
 * Description: Set's the player's death flag
 * Pre: deadStatus is true if the player is dead, false otherwise
 * Post: Character's dead flag is set to deadStatus
 * Returns: none
 */
void Character::setDead(bool deadStatus){
	dead = deadStatus;
}

/*
 * addAttack
 * Description: Adds an attack to the Characters
 * Pre: deadStatus is true if the player is dead, false otherwise
 * Post: Character's dead flag is set to deadStatus
 * Returns: none
 */
void Character::addAttack(const AttackType& attack){
	attacks.push_back(attack);	// add new attack to attacks vector
	unlockedAttacks.push_back(true);	// set new attack to unlocked
}

// virtual function implementations
std::string Character::getClassName()const{
	return "Character";
}

void Character::unlockAttack(int index){
	unlockedAttacks[index] = true;
}

void Character::loadCharacter(istream& in)
{
    int i = 0, eListSize = 0, aListSize = 0;
    AttackType a;
    EquipmentType * e = new EquipmentType();
    bool lock;
    char *tk = NULL;// pointers to chars
    char data[MAX] = ""; //to hold line
    in.getline(data,MAX - 1, '\n');
    tk = strtok(data, DELIMS); // get next token
    Base::setObjectID(atoi(tk));
    tk = strtok(NULL, DELIMS); // get next token
    setDesc(tk);
    tk = strtok(NULL, DELIMS); // get next token
    setObjectType(tk);
    tk = strtok(NULL, DELIMS); // get next token
    switch(atoi(tk))
    {
        case 0:
            characterClass = WARRIOR;
            break;
        case 1:
            characterClass = WIZARD;
            break;
        case 2:
            characterClass = RANGER;
            break;
    }
    tk = strtok(NULL, DELIMS); // get next token
    dead = atoi(tk);
    in.getline(data,MAX - 1, '\n');
    tk = strtok(data, DELIMS); // get next token
   // std::cout<<"alistsize "<<tk;
    aListSize = atoi(tk);
    tk = strtok(NULL, DELIMS); // get next token
    eListSize = atoi(tk);
    for(i = 0; i < aListSize; ++i)
    {
        in >> a;
        attacks.push_back(a);
    }

    for(i = 0; i < aListSize; ++i)
    {
        in >> lock;
        unlockedAttacks.push_back(lock);
    }
    in.ignore();
    for(i = 0; i < eListSize; ++i)
    {
        in >> *e;
        equipment.push_back(e);
    }
	inventory.loadInventory(in);
}


void Character::saveCharacter(ostream& out)
{
    int i = 0;
    out << getObjectID() << ',' << getDesc() << ',' << getObjectType() << ',' << characterClass << ',' << dead << endl
        << attacks.size() << ',' << equipment.size() << endl;
    for(i = 0; i < attacks.size(); ++i)
    {
        out << attacks.at(i) << endl;
    }
    for(i = 0; i < attacks.size(); ++i)
    {
        out << unlockedAttacks.at(i) << endl;
    }
    for(i = 0; i < equipment.size(); ++i)
    {
        out << *equipment.at(i) << endl;
    }
	inventory.saveInventory(out);
}
